/* Payment Platform from Lucky Byte, Inc.
 *
 * Copyright (c) 2016 Lucky Byte, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lucky_byte.pay.tpdu;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Properties;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * TPDU 网控
 */
public class Console
{
	private static final Logger logger = LogManager.getLogger();

	public static void main(String[] args) {
		String tpdu_base = System.getProperty("TPDU.BASE");
		if (tpdu_base == null) {
			logger.error("没有定义系统变量[TPDU.BASE]，"
					+ "请在启动时使用 Java 命令选项[-DTPDU.BASE=...].");
			return;
		}
		File file = new File(tpdu_base + "/etc/tpdu.properties");
		try {
			Properties properties = new Properties();
			properties.load(new FileInputStream(file));

			Derby derby = new Derby(tpdu_base);
			if (!derby.open()) {
				logger.error("打开数据库错误，退出程序.");
				return;
			}
			PooledServer server = new PooledServer(properties);
			Thread server_thread = new Thread(server);
			server_thread.setDaemon(true);
			server_thread.start();

			Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
				public void run() {
					logger.info("TPDU 网控开始退出...");
					server.stop();
					derby.close();
				}
			}));

			WatchService watchService =
					FileSystems.getDefault().newWatchService();
			Path path = new File(tpdu_base + "/etc").toPath();
			path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
			while (true) {
				final WatchKey key = watchService.take();
				for (WatchEvent<?> event : key.pollEvents()) {
					Path changed = (Path) event.context();
					if (changed.endsWith("tpdu.properties")) {
						logger.info("检测到配置文件[{}]被修改，重新加载...",
								changed.toString());
						file = new File(path.toString() + "/" +
								changed.toString());
						properties = new Properties();
						properties.load(new FileInputStream(file));
						server.setProperties(properties);
					} else if (changed.endsWith("db_backup.conf")) {
						logger.info("检测到配置文件[{}]被修改，开始备份数据库...",
								changed.toString());
						derby.backup(tpdu_base);
					}
				}
				if (!key.reset()) {
					logger.warn("继续检测配置文件修改失败，配置文件修改后系统将"
							+ "不能自动加载新配置，请联系开发人员分析原因.");
				}
				if (!server_thread.isAlive()) {
					break;
				}
			}
		} catch (InterruptedException e) {
			logger.info("TPDU 网控线程被外部中断，停止运行.");
		} catch (IOException e) {
			logger.error("加载或监听 TPDU 配置文件[{}]错误[{}].",
					file.getPath(), e.getMessage());
		} catch (Exception e) {
			logger.catching(e);
		}
	}

}